//+--------------------------------------------------------------------
//| Copyright(c) 2012 - an.vuongngocduy					
//| This file is a part of Compact Game Engine (CGE)	
//+--------------------------------------------------------------------
#ifndef __CGE_RECT_H__
#define __CGE_RECT_H__

#include "cgeVector2.h"
#include "cgeSize2.h"

namespace cge
{
	namespace std
	{
		template<class TVal>
		class Rect
		{
		public:
			/// Default constructor
			Rect()
				: Left(0), Top(0), Right(0), Bottom(0)
			{}

			/// Construct new rectangle from specified elements
			Rect(TVal l, TVal t, TVal r, TVal b)
				: Left(l), Top(t), Right(r), Bottom(b)
			{}

			/// Destructor
			~Rect() {}

			/// Get size of rectangle
			Size2<TVal> Size() const
			{
				return Size2<TVal>(Right - Left, Bottom - Top);
			}

			/// Set elements' values for rectangle
			void Set(TVal l, TVal t, TVal r, TVal b)
			{
				Left = l; Top = t; Right = r; Bottom = b;
			}

			/// Set elements' values for rectangle from position and size
			void Set(const Vector2<TVal>& topLeftPos, const Size2<TVal>& dimension)
			{
				Left = topLeftPos.X; Top = topLeftPos.Y; Right = Left + dimension.Width; Bottom = Top + dimension.Height;
			}

			/// Test whether 2 rectangles collided with each other
			template<class TArg>
			b8 IsCollided(const Rect<TArg>& rect) const
			{
				b8 isCollided = ( Right > rect.Left && Bottom > rect.Top )
							  ||( Left < rect.Right && Top < rect.Bottom )
							  ||( Left < rect.Right && Bottom > rect.Top )
							  ||( Right > rect.Left && Top < rect.Bottom );			
				return isCollided;
			}

			/// Get intersection rect between 2 rectangle . If there are no intersection , the returned rect will have 0 area
			template<class TArg>
			Rect GetIntersection(const Rect<TArg>& rect) const
			{
				Rect res;

				if( Right > rect.Left && Bottom > rect.Top )
					res.Set(rect.Left, rect.Top, Right, Bottom);
				
				if( Left < rect.Right && Top < rect.Bottom )
					res.Set(Left, Top, rect.Right, rect.Bottom); 
				
				if( Left < rect.Right && Bottom > rect.Top )
					res.Set(Left, Rect.Top, rect.Right, Bottom);
				
				if( Right > rect.Left && Top < rect.Bottom )
					res.Set(rect.Left, Top, Right, rect.Bottom);

				return res;
			}

		public:
			union
			{
				struct {  TVal Left, Top, Right, Bottom; };
				TVal Elements[4];
			};
		};

		typedef Rect<u32> Rectu;

		typedef Rect<s32> Recti;

		typedef Rect<f32> Rectf;

		typedef Rect<f64> Rectd;
	}
}

#endif//__CGE_RECT_H__